home *** CD-ROM | disk | FTP | other *** search
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <stdio.h>
- #include <FixMath.h>
- #include <Resources.h>
-
- #include "sfnt.h"
- #include "Access.h"
-
- /********************* Private functions *****************/
-
- long PostFontError(long error)
- {
- if (error)
- Debugger();
- }
-
- static short GetFontState(Handle sfnt)
- {
- short state;
-
- LoadResource(sfnt);
- state = HGetState(sfnt);
- HNoPurge(sfnt);
- return state;
- }
-
- static void SetFontState(Handle sfnt, short state)
- {
- HSetState(sfnt, state);
- }
-
- /* Macro and glue routine to make handle growing easier.
- */
- #define SHS(h, s) NiceSetHandleSize((Handle)h, s)
-
- static short NiceSetHandleSize(Handle h, long size)
- {
- SetHandleSize(h, size);
- return MemError();
- }
-
- /* Some private calls to return pointers to various sfnt pieces.
- */
- static void* GetSfntTablePtr(Handle sfnt, fontTableTag tag)
- {
- FontTableInfo info;
-
- if (GetSfntTableInfo(sfnt, tag, &info))
- return 0;
- return *sfnt + info.offset;
- }
-
- static void* GetSfntGlyphPtr(Handle sfnt, long glyphIndex, long* length)
- {
- void* loc;
- char* glyphStart;
- sfnt_FontHeader* head;
-
- if (!((head = GetSfntTablePtr(sfnt, tag_FontHeader)) &&
- (loc = GetSfntTablePtr(sfnt, tag_IndexToLoc)) &&
- (glyphStart = GetSfntTablePtr(sfnt, tag_GlyphData))))
- return 0;
-
- if (head->indexToLocFormat == SHORT_INDEX_TO_LOC_FORMAT)
- { unsigned short* offset = (unsigned short*)loc + glyphIndex;
- *length = (long)(offset[1] - *offset) << 1;
- return glyphStart + ((long)*offset << 1);
- }
- else
- { long* offset = (long*)loc + glyphIndex;
- *length = offset[1] - *offset;
- return glyphStart + *offset;
- }
- }
-
- /********************** Public Font Tool Calls *******************/
-
- long CountSfntTables(Handle sfnt)
- {
- short state = GetFontState(sfnt);
- short tables = ((sfnt_OffsetTable*)*sfnt)->numOffsets;
- SetFontState(sfnt, state);
- return tables;
- }
-
- fontTableTag GetSfntTag(Handle sfnt, long index)
- {
- fontTableTag tag = 0;
- short state = GetFontState(sfnt);
- if (index < ((sfnt_OffsetTable*)*sfnt)->numOffsets)
- tag = ((sfnt_OffsetTable*)*sfnt)->table[index].tableTag;
- SetFontState(sfnt, state);
- return tag;
- }
-
- FontError GetSfntTableInfo(Handle sfnt, fontTableTag tag, FontTableInfo* fTable)
- {
- short state = GetFontState(sfnt);
- register sfnt_OffsetTable* dir = (sfnt_OffsetTable*)*sfnt;
- register sfnt_DirectoryEntry* table = dir->table;
- register short count = dir->numOffsets;
- FontError error = fNoError;
-
- for (; --count >= 0; table++)
- if (table->tableTag == tag)
- { fTable->offset = table->offset;
- fTable->length = table->length;
- fTable->checkSum = table->checkSum;
- break;
- }
- if (count < 0)
- error = PostFontError(fTableNotFound);
- SetFontState(sfnt, state);
- return error;
- }
-
- FontError GetSfntTable(Handle sfnt, fontTableTag tag, Handle userCopy)
- {
- FontTableInfo info;
- FontError error;
-
- if (error = GetSfntTableInfo(sfnt, tag, &info))
- return error;
-
- SetHandleSize(userCopy, info.length);
- if (MemError())
- return PostFontError(fMemoryError);
-
- { short state = GetFontState(sfnt);
- BlockMove(*sfnt + info.offset, *userCopy, info.length);
- SetFontState(sfnt, state);
- }
- return fNoError;
- }
-
- FontError GetSfntNameString(Handle sfnt, long nameID, Str255 name)
- {
- register sfnt_NamingTable* nameT;
- register sfnt_NameRecord* nameR;
- register short count;
- short state = GetFontState(sfnt);
-
- if (!(nameT = GetSfntTablePtr(sfnt, tag_NamingTable)))
- { SetFontState(sfnt, state);
- return fTableNotFound;
- }
-
- nameR = (sfnt_NameRecord*)(nameT + 1);
- count = nameT->count;
-
- /* This section can be changed to get font names in other languages
- */
- for (; --count >= 0; nameR++)
- if (nameR->platformID == plat_Macintosh &&
- nameR->specificID == smRoman &&
- nameR->languageID == lang_English &&
- nameR->nameID == nameID)
- {
- name[0] = nameR->length <= 255 ? nameR->length : 255;
- BlockMove((Ptr)nameT + nameT->stringOffset + nameR->offset, (Ptr)&name[1], name[0]);
- SetFontState(sfnt, state);
- return fNoError;
- }
-
- name[0] = 0;
- SetFontState(sfnt, state);
- return fNameNotFound;
- }
-
- /* Returns the glyph index for the given character code, or
- * an error code.
- */
- long GetCharGlyphIndex(Handle sfnt, unsigned short charCode)
- {
- sfnt_char2IndexDirectory* table;
- short i;
- long mapOffset = 0;
- long glyphIndex = 0; /* missing character glyph */
- short state = GetFontState(sfnt);
-
- if (!(table = GetSfntTablePtr(sfnt, tag_CharToIndexMap)))
- { SetFontState(sfnt, state);
- return PostFontError(fTableNotFound);
- }
-
- { register sfnt_platformEntry* plat = table->platform;
-
- /* You can change this section to look for other scripts
- */
- for ( i = table->numTables - 1; i >= 0; --i )
- { if ( plat->platformID == plat_Macintosh && plat->specificID == smRoman)
- { mapOffset = plat->offset;
- break;
- }
- ++plat;
- }
- }
-
- if (mapOffset)
- { sfnt_mappingTable* mapping = (sfnt_mappingTable*)((char*)table + mapOffset);
-
- switch ( mapping->format ) {
- case 0:
- { Byte* glyphs = (Byte*)(mapping + 1);
- glyphIndex = glyphs[charCode];
- }
- break;
- case 6:
- { short* glyphs = (short*)(mapping + 1);
- short first = *glyphs++;
- short count = *glyphs++;
- charCode -= first;
- if (charCode < count)
- glyphIndex = glyphs[charCode];
- }
- break;
- default:
- glyphIndex = PostFontError(fUnimplemented);
- }
- }
- else
- glyphIndex = PostFontError(fCMapNotFound);
-
- SetFontState(sfnt, state);
- return glyphIndex;
- }
-
- long CountSfntGlyphs(Handle sfnt)
- {
- sfnt_maxProfileTable* profile;
- short glyphs;
-
- if (!(profile = GetSfntTablePtr(sfnt, tag_MaxProfile)))
- return PostFontError(fTableNotFound);
-
- { short state = GetFontState(sfnt);
- glyphs = profile->numGlyphs;
- SetFontState(sfnt, state);
- }
- return glyphs;
- }
-
- #define GetUnsignedByte( p ) ((Byte)(*p++))
-
- FontError GetGlyphOutline(Handle sfnt, long glyphIndex, GlyphOutline* gOutline, Matrix xform)
- {
- short upem, state, sideBearing, adjustToLsb;
- short* glyph;
- sfnt_FontHeader* head;
- sfnt_HorizontalHeader* hhea;
- sfnt_HorizontalMetrics* hori;
- long length;
- FontError error = fNoError;
-
- state = GetFontState( sfnt );
- HLock( sfnt );
-
- if (!((head = GetSfntTablePtr(sfnt, tag_FontHeader)) &&
- (hhea = GetSfntTablePtr(sfnt, tag_HoriHeader)) &&
- (hori = GetSfntTablePtr(sfnt, tag_HorizontalMetrics))))
- { error = fTableNotFound;
- goto EXIT;
- }
-
- upem = head->unitsPerEm;
-
- { long longMetrics = hhea->numberLongMetrics;
- if ( glyphIndex < longMetrics )
- { gOutline->advance.x = FixRatio( hori[glyphIndex].advance, upem );
- sideBearing = hori[glyphIndex].sideBearing;
- }
- else
- { short *lsb = (short *)&hori[longMetrics]; /* first entry after[AW,LSB] array */
-
- gOutline->advance.x = FixRatio( hori[longMetrics-1].advance, upem );
- sideBearing = hori[glyphIndex - longMetrics].sideBearing;
- }
- gOutline->advance.y = 0;
- }
-
- gOutline->origin.x = gOutline->origin.y = 0;
-
- if (!(glyph = GetSfntGlyphPtr(sfnt, glyphIndex, &length)))
- { error = fGlyphNotFound;
- goto EXIT;
- }
-
- if (length == 0)
- { gOutline->contourCount = gOutline->pointCount = 0;
- goto EXIT;
- }
-
- gOutline->contourCount = *glyph++;
- adjustToLsb = *glyph - sideBearing; /* xmin - lsb */
- glyph += 4; /* skip bounds rect */
-
- if (gOutline->contourCount == 0)
- gOutline->pointCount = 0;
- else if (gOutline->contourCount == -1)
- { short flags, index, newMatrix;
-
- gOutline->contourCount = gOutline->pointCount = 0;
- SHS(gOutline->endPoints, 0);
- SHS(gOutline->onCurve, 0);
- SHS(gOutline->x, 0);
- SHS(gOutline->y, 0);
- do
- { Matrix compXform;
- short arg1, arg2;
-
- flags = *glyph++;
- index = *glyph++;
- newMatrix = false;
-
- if ( flags & ARG_1_AND_2_ARE_WORDS )
- { arg1 = *glyph++;
- arg2 = *glyph++;
- }
- else
- { char* byteP = (char*)glyph;
- if ( flags & ARGS_ARE_XY_VALUES )
- { /* offsets are signed */
- arg1 = *byteP++;
- arg2 = *byteP;
- }
- else
- { /* anchor points are unsigned */
- arg1 = (unsigned char)*byteP++;
- arg2 = (unsigned char)*byteP;
- }
- ++glyph;
- }
- #if IMPLEMENT_SCALED_COMPONENTS
- if ( flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO) )
- { Matrix subXform;
- MakeIdentityMatrix(subXform);
- if ( flags & WE_HAVE_A_TWO_BY_TWO )
- { compXform[0][0] = (Fixed)*glyph++ << 2;
- compXform[0][1] = (Fixed)*glyph++ << 2;
- compXform[1][0] = (Fixed)*glyph++ << 2;
- compXform[1][1] = (Fixed)*glyph++ << 2;
- }
- else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE )
- { compXform[0][0] = (Fixed)*glyph++ << 2;
- compXform[1][1] = (Fixed)*glyph++ << 2;
- }
- else
- compXform[0][0] = compXform[1][1] = (Fixed)*glyph++ << 2;
- PostMulMatrix(compXform, xform);
- newMatrix = true;
- }
- #endif
- { GlyphOutline out;
- InitGlyphOutline(&out);
- GetGlyphOutline(sfnt, index, &out, newMatrix ? compXform : xform);
- { Fixed dx, dy;
- if (flags & ARGS_ARE_XY_VALUES)
- { dx = FixRatio(arg1, upem);
- dy = -FixRatio(arg2, upem);
- }
- else
- { dx = (*gOutline->x)[arg1] - (*out.x)[arg2];
- dy = (*gOutline->y)[arg1] - (*out.y)[arg2];
- }
- MoveGlyphOutline(&out, dx, dy);
- }
- AppendGlyphOutline(gOutline, &out);
- KillGlyphOutline(&out);
- }
- } while (flags & MORE_COMPONENTS);
- }
- else if (gOutline->contourCount > 0)
- { /* Load in the end points.
- */
- { long size = gOutline->contourCount * sizeof(short);
-
- if (SHS(gOutline->endPoints, size))
- { error = fMemoryError;
- goto EXIT;
- }
- BlockMove( (Ptr)glyph, (Ptr)*gOutline->endPoints, size );
- glyph += gOutline->contourCount;
- }
-
- gOutline->pointCount = (*gOutline->endPoints)[gOutline->contourCount - 1] + 1;
- if (SHS(gOutline->onCurve, gOutline->pointCount * sizeof(char)))
- { error = fMemoryError;
- goto EXIT;
- }
- if (SHS(gOutline->x, gOutline->pointCount * sizeof(Fixed)))
- { error = fMemoryError;
- goto EXIT;
- }
- if (SHS(gOutline->y, gOutline->pointCount * sizeof(Fixed)))
- { error = fMemoryError;
- goto EXIT;
- }
-
- /* Skip the word for instruction count + the instructions.
- * Then load in the onCurve bytes.
- */
- { Byte* p = (Byte*)glyph + sizeof(short) + *glyph;
- Byte* onCurve = *gOutline->onCurve;
- Byte* stop = onCurve + gOutline->pointCount;
- Byte flag;
-
- while (onCurve < stop)
- { *onCurve++ = flag = GetUnsignedByte( p );
- if ( flag & REPEAT_FLAGS ) {
- short count = GetUnsignedByte( p );
- for (--count; count >= 0; --count)
- *onCurve++ = flag;
- }
- }
- /* Lets do X
- */
- { short coord = adjustToLsb;
- Fixed* x = *gOutline->x;
-
- onCurve = *gOutline->onCurve;
- while (onCurve < stop)
- { if ( (flag = *onCurve++) & XSHORT ) {
- if ( flag & SHORT_X_IS_POS )
- coord += GetUnsignedByte( p );
- else
- coord -= GetUnsignedByte( p );
- }
- else if ( !(flag & NEXT_X_IS_ZERO) )
- { coord += (short)(*p++) << 8;
- coord += (Byte)*p++;
- }
- *x++ = FixRatio( coord, upem );
- }
- }
- /* Lets do Y
- */
- { short coord = 0;
- Fixed* y = *gOutline->y;
-
- onCurve = *gOutline->onCurve;
- while (onCurve < stop)
- { if ( (flag = *onCurve) & YSHORT ) {
- if ( flag & SHORT_Y_IS_POS )
- coord += GetUnsignedByte( p );
- else
- coord -= GetUnsignedByte( p );
- }
- else if ( !(flag & NEXT_Y_IS_ZERO) )
- { coord += (short)(*p++) << 8;
- coord += (Byte)*p++;
- }
- *y++ = -FixRatio( coord, upem );
-
- /* Filter off the extra bits
- */
- *onCurve++ = flag & ONCURVE;
- }
- }
- }
- }
- else
- error = fUnimplemented;
- EXIT:
- SetFontState( sfnt, state );
-
- return PostFontError(error);
- }
-
-